"""
服务对象 - 负责温度计算和计费
"""
from datetime import datetime
from typing import Optional
import threading
from . import config
from .models import RoomState, BillingDetail


class ServiceObject:
    """服务对象类"""
    
    _id_counter = 0
    _id_lock = threading.Lock()
    
    def __init__(self):
        with ServiceObject._id_lock:
            self.id = ServiceObject._id_counter
            ServiceObject._id_counter += 1
        
        self.room_id: Optional[str] = None
        self.is_free = True
        self.start_time: Optional[datetime] = None
        self.start_temp: Optional[float] = None
        
    def allocate(self, room_id: str, room_state: RoomState):
        """分配服务对象给房间"""
        self.room_id = room_id
        self.is_free = False
        self.start_time = datetime.now()
        self.start_temp = room_state.current_temp
        room_state.is_serving = True
        room_state.last_update_time = self.start_time
        
    def release(self, room_state: RoomState) -> Optional[BillingDetail]:
        """释放服务对象"""
        if self.room_id is None:
            return None
        
        # 生成详单（只记录本次服务的详细信息，不重复累加费用）
        end_time = datetime.now()
        duration_seconds = (end_time - self.start_time).total_seconds()
        duration_minutes = duration_seconds / 60.0
        
        # 计算本次服务的耗电量和费用（仅用于详单记录）
        power_consumption = self.calculate_power_consumption(
            room_state.wind_speed, duration_minutes
        )
        cost = power_consumption * config.COST_PER_UNIT
        
        detail = BillingDetail(
            room_id=self.room_id,
            start_time=self.start_time,
            end_time=end_time,
            wind_speed=room_state.wind_speed,
            start_temp=self.start_temp,
            end_temp=room_state.current_temp,
            target_temp=room_state.target_temp,
            duration_minutes=duration_minutes,
            power_consumption=power_consumption,
            cost=cost
        )
        
        # 仅添加详单记录，不再重复累加费用（费用已在每秒更新中累加）
        room_state.billing_details.append(detail)
        room_state.is_serving = False
        
        # 重置服务对象
        self.room_id = None
        self.is_free = True
        self.start_time = None
        self.start_temp = None
        
        return detail
    
    @staticmethod
    def calculate_power_consumption(wind_speed: str, duration_minutes: float) -> float:
        """计算耗电量"""
        rate = config.POWER_CONSUMPTION.get(wind_speed, 0)
        return rate * duration_minutes
    
    @staticmethod
    def calculate_temp_change(current_temp: float, target_temp: float, 
                            wind_speed: str, mode: str, 
                            duration_minutes: float) -> float:
        """计算温度变化
        
        Args:
            current_temp: 当前温度
            target_temp: 目标温度
            wind_speed: 风速
            mode: 模式（制冷/制热）
            duration_minutes: 持续时间（分钟）
            
        Returns:
            新的温度值
        """
        rate = config.TEMP_CHANGE_RATE.get(wind_speed, 0)
        temp_change = rate * duration_minutes
        
        if mode == config.MODE_COOLING:
            # 制冷模式：温度降低
            new_temp = current_temp - temp_change
            return max(new_temp, target_temp)  # 不低于目标温度
        else:
            # 制热模式：温度升高
            new_temp = current_temp + temp_change
            return min(new_temp, target_temp)  # 不高于目标温度
    
    @staticmethod
    def calculate_temp_change_off(current_temp: float, initial_temp: float,
                                  duration_minutes: float) -> float:
        """计算关机状态下的温度变化
        
        Args:
            current_temp: 当前温度
            initial_temp: 初始温度
            duration_minutes: 持续时间（分钟）
            
        Returns:
            新的温度值
        """
        rate = config.TEMP_CHANGE_RATE_OFF
        temp_change = rate * duration_minutes
        
        if current_temp < initial_temp:
            # 温度回升
            new_temp = current_temp + temp_change
            return min(new_temp, initial_temp)
        elif current_temp > initial_temp:
            # 温度下降
            new_temp = current_temp - temp_change
            return max(new_temp, initial_temp)
        else:
            return current_temp
    
    @staticmethod
    def should_restart(current_temp: float, target_temp: float, mode: str) -> bool:
        """判断是否需要重新启动
        
        当房间温度超过目标温度1度时，重新启动
        """
        if mode == config.MODE_COOLING:
            # 制冷模式：当前温度比目标温度高1度以上
            return current_temp >= target_temp + config.TEMP_THRESHOLD
        else:
            # 制热模式：当前温度比目标温度低1度以上
            return current_temp <= target_temp - config.TEMP_THRESHOLD
    
    @staticmethod
    def is_target_reached(current_temp: float, target_temp: float) -> bool:
        """判断是否达到目标温度"""
        return abs(current_temp - target_temp) < 0.01  # 误差范围0.01度

